#include <srs_app_async_call.hpp>

using namespace std;

#include <srs_kernel_error.hpp>
#include <srs_kernel_log.hpp>

// the sleep interval for http async callback.
#define SRS_AUTO_ASYNC_CALLBACL_SLEEP_US 300000

ISrsAsyncCallTask::ISrsAsyncCallTask() {
}

ISrsAsyncCallTask::~ISrsAsyncCallTask() {
}

SrsAsyncCallWorker::SrsAsyncCallWorker()
    : running(false) {
    pthread = new SrsReusableThread("async", this, SRS_AUTO_ASYNC_CALLBACL_SLEEP_US);
}

SrsAsyncCallWorker::~SrsAsyncCallWorker() {
    srs_freep(pthread);

    for (auto it = tasks.begin(); it != tasks.end(); ++it) {
        auto task = *it;
        srs_freep(task);
    }
    tasks.clear();
}

int SrsAsyncCallWorker::execute(ISrsAsyncCallTask* t) {
    int ret = ERROR_SUCCESS;
    tasks.push_back(t);
    return ret;
}

int SrsAsyncCallWorker::start() {
    if (running == false) {
        running = true;
        return pthread->start();
    }
    return ERROR_SUCCESS;
}

void SrsAsyncCallWorker::stop() {
    pthread->stop();
}

int SrsAsyncCallWorker::cycle() {
    int ret = ERROR_SUCCESS;

    auto copies = std::move(tasks);
    tasks.clear();

    for (auto it = copies.begin(); it != copies.end(); ++it) {
        auto task = *it;
        if (task != nullptr && (ret = task->call()) != ERROR_SUCCESS) {
            srs_warn("ignore async callback %s, ret=%d", task->to_string().c_str(), ret);
        }
        srs_freep(task);
    }
    return ret;
}
